package com.example.springflowable.service.impl;

import com.example.springflowable.ask_for_leave.service.impl.AskLeaveTaskServiceImpl;
import com.example.springflowable.model.TaskModel;
import com.example.springflowable.service.TaskCommonService;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.impl.identity.Authentication;
import org.flowable.engine.*;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.engine.runtime.ProcessInstanceBuilder;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @Classname TaskCommonImpl
 * @Description TODO
 * @Date 2022/5/6 16:14
 * @Created by XiongXiong
 * @Author: X.I.O
 */
@Service
public class TaskCommonImpl implements TaskCommonService {

    @Autowired
    private TaskService taskService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private ManagementService managementService;

    Logger logger= LoggerFactory.getLogger(TaskCommonImpl.class);

    @Override
    public void addCheckMessage(String taskId, String message) {
        Task task=taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task != null) {
            taskService.addComment(taskId,task.getProcessInstanceId(),message);
        }
    }


    @Override
    public ProcessInstance startProcess(String processdefId, String businessId, String title,String uid, Map<String,Object> map) {
        Authentication.setAuthenticatedUserId(uid);
        ProcessInstanceBuilder processInstanceBuilder=runtimeService.createProcessInstanceBuilder();
        processInstanceBuilder.businessKey(businessId);
        processInstanceBuilder.processDefinitionKey(processdefId);
        processInstanceBuilder.name(title);
        processInstanceBuilder.variables(map);
        ProcessInstance processInstance=processInstanceBuilder.start();
        Authentication.setAuthenticatedUserId(null);
        return processInstance;
    }

    @Override
    public void deleteDeployment(String deploymentId) {
        repositoryService.deleteDeployment(deploymentId ,true);
    }

    @Override
    public void activateProcessInstanceById(String processInstanceId) {
        runtimeService.activateProcessInstanceById(processInstanceId);
    }

    @Override
    public void suspendProcessInstanceById(String processInstanceId) {
        runtimeService.suspendProcessInstanceById(processInstanceId);
    }

    @Override
    public List<ProcessInstance> getProcessInstanceList() {
        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery().list();
        for (ProcessInstance processInstance : list) {
            System.out.println(processInstance.getStartTime()+"|"+processInstance.getProcessInstanceId()+"|"+
                    processInstance.getStartUserId()+"|"+processInstance.getProcessDefinitionName()+":"+
                    processInstance.isSuspended());
        }
        return list;
    }

    @Override
    public List<HistoricTaskInstance> getHistoricTaskInstanceListByUid(String uid) {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                //按结束时间正向排序
                .orderByHistoricTaskInstanceEndTime().asc()
                .taskAssignee(uid).list();
        for (HistoricTaskInstance historicTaskInstance : list) {
            System.out.println("task "+historicTaskInstance.getName()+" == "+historicTaskInstance.getAssignee());
        }
        return list;
    }

    @Override
    public ProcessInstance getProcessInstanceByTaskId(String taskId) {
        Task task=taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            return null;
        }
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
        return processInstance;
    }

    @Override
    public ProcessInstance getProcessInstanceById(String processInstanceId) {
        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        return processInstance;
    }

    @Override
    public Task getTaskByProcessInstanceId(String processInstanceId) {
        return taskService.createTaskQuery().processInstanceId(processInstanceId).singleResult();
    }

    @Override
    public List<TaskModel> getMyTaskList(String uid,Integer page,Integer size) {
        List<Task> tasks = taskService.createTaskQuery()
                .taskAssignee(uid)
                .orderByTaskCreateTime().desc()
                .listPage(page,size);
        if(tasks==null || tasks.size() == 0){
            return Collections.emptyList();
        }
        List<TaskModel> taskModels=new ArrayList<>();
        if(tasks!=null){
            TaskModel taskModel=null;
            for (Task task : tasks) {
                taskModel=new TaskModel();
                ProcessInstance processInstance=runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                taskModel.setTaskId(task.getId());
                taskModel.setTaskName(task.getName());
                taskModel.setTitle(processInstance.getName());
                taskModel.setProcessId(processInstance.getId());
                taskModel.setBindID(processInstance.getBusinessKey());
                taskModel.setFromUID(task.getOwner());
                taskModel.setToUID(task.getAssignee());
                taskModels.add(taskModel);
            }
        }
        return taskModels;
    }

    @Override
    public void complete(String taskId, String formUid, String toUid, String msg, Map<String, Object> map) {
        Task task=taskService.createTaskQuery().taskId(taskId).singleResult();
        Authentication.setAuthenticatedUserId(toUid);
        logger.info("任务 ID：{}；任务处理人：{}；任务是否挂起：{}", task.getId(), task.getAssignee(), task.isSuspended());
        taskService.addComment(taskId,task.getProcessInstanceId(),msg);
        taskService.complete(task.getId(), map);
        Authentication.setAuthenticatedUserId(null);
    }

    @Override
    public void complete(String processInstanceId, String toUid, String msg, Map<String, Object> map) {
        List<Task> taskList=getTaskListByProcessInstanceId(processInstanceId);
        if(taskList == null || taskList.size() == 0){
            return;
        }
        Task task=taskList.get(0);
       // taskService.claim(task.getId(),toUid);
        taskService.addComment(task.getId(),task.getProcessInstanceId(),msg);
        taskService.complete(task.getId(), map);
    }

    @Override
    public List<TaskModel> getMyHistoryTaskList(String uid, Integer page, Integer size) {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                //按结束时间正向排序
                .orderByHistoricTaskInstanceEndTime().asc()
                .taskAssignee(uid).listPage(page,size);
        List<TaskModel> taskModelList=new ArrayList<>();
        for (HistoricTaskInstance historicTaskInstance : list) {
            String processInstanceId=historicTaskInstance.getProcessInstanceId();
            ProcessInstance processInstance=runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
            if(processInstance!=null){
                TaskModel taskModel=new TaskModel();
                taskModel.setTaskId(historicTaskInstance.getId());
                taskModel.setTaskName(historicTaskInstance.getName());
                taskModel.setTitle(processInstance.getName());
                taskModel.setProcessId(processInstance.getId());
                taskModel.setBindID(processInstance.getBusinessKey());
                taskModel.setFromUID(historicTaskInstance.getOwner());
                taskModel.setToUID(historicTaskInstance.getAssignee());
                taskModelList.add(taskModel);
            }else {
                HistoricProcessInstance historicProcessInstance=historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
                TaskModel taskModel=new TaskModel();
                taskModel.setTaskId(historicTaskInstance.getId());
                taskModel.setTaskName(historicTaskInstance.getName());
                taskModel.setTitle(historicProcessInstance.getName());
                taskModel.setProcessId(historicProcessInstance.getId());
                taskModel.setBindID(historicProcessInstance.getBusinessKey());
                taskModel.setFromUID(historicTaskInstance.getOwner());
                taskModel.setToUID(historicTaskInstance.getAssignee());
                taskModelList.add(taskModel);
            }
        }
        return taskModelList;
    }



    @Override
    public List<TaskModel> getHistoryTaskListByProcessInstanceId(String processInstanceId) {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery().processInstanceId(processInstanceId).list();
        System.out.println(list.size());
        HistoricProcessInstance processInstance=historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
        List<TaskModel> taskModelList=new ArrayList<>();
        for (HistoricTaskInstance historicTaskInstance : list) {
            TaskModel taskModel=new TaskModel();
            taskModel.setTaskId(historicTaskInstance.getId());
            taskModel.setTaskName(historicTaskInstance.getName());
            taskModel.setTitle(processInstance.getName());
            taskModel.setProcessId(processInstance.getId());
            taskModel.setBindID(processInstance.getBusinessKey());
            taskModel.setFromUID(historicTaskInstance.getOwner());
            taskModel.setToUID(historicTaskInstance.getAssignee());
            taskModelList.add(taskModel);
        }
        return taskModelList;
    }

    @Override
    public List<HistoricTaskInstance> getHistoricTaskListByProcessInstanceId(String processInstId) {
        List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
                .orderByHistoricTaskInstanceEndTime().asc()
                .processInstanceId(processInstId).list();
        return list;
    }

    @Override
    public List<Task> getTaskListByProcessInstanceId(String processInstanceId) {
        return taskService.createTaskQuery().processInstanceId(processInstanceId).list();
    }

    @Override
    public List<TaskModel> getTaskModelListByProcessInstanceId(String processInstanceId) {
        List<Task> tasks=taskService.createTaskQuery().processInstanceId(processInstanceId).list();
        List<TaskModel> taskModels=new ArrayList<>();
        if(tasks != null){
            for (Task task : tasks) {
                TaskModel taskModel=new TaskModel();
                ProcessInstance processInstance=runtimeService.createProcessInstanceQuery().processInstanceId(task.getProcessInstanceId()).singleResult();
                taskModel.setTaskId(task.getId());
                taskModel.setTaskName(task.getName());
                taskModel.setTitle(processInstance.getName());
                taskModel.setProcessId(processInstance.getId());
                taskModel.setBindID(processInstance.getBusinessKey());
                taskModel.setFromUID(task.getOwner());
                taskModel.setToUID(task.getAssignee());
                taskModels.add(taskModel);
            }
        }
        return taskModels;
    }

    @Override
    public void dealGetWay(FlowElement flowElement,Map data) {
        List<SequenceFlow> targetFlows=((ExclusiveGateway)flowElement).getOutgoingFlows();
        // 循环每个网关分支
        for(SequenceFlow sequenceFlow : targetFlows) {
            // 获取下一个网关和节点数据
            FlowElement targetFlowElement = sequenceFlow.getTargetFlowElement();
            // 网关数据不为空
            if (sequenceFlow.getConditionExpression() != null && !"".equals(sequenceFlow.getConditionExpression())) {
                //计算连接线上的表达式
                //  Object result = managementService.executeCommand(new ExpressionEvaluateUtil(sequenceFlow.getConditionExpression(), data));
                System.out.println("排他网关中线条: id=" + sequenceFlow.getId() + ",name=" + sequenceFlow.getName() + ",result=,ConditionExpression=" + sequenceFlow.getConditionExpression());
                // 获取网关判断条件
                String conditionExpression = null;
                if (sequenceFlow.getConditionExpression() != null) {
                    conditionExpression = sequenceFlow.getConditionExpression().substring(sequenceFlow.getConditionExpression().indexOf("==") + 2,
                            sequenceFlow.getConditionExpression().indexOf("}"));
                }
                System.out.println("截取后的选择条件: id=" + conditionExpression);
            }
            // 网关的下个节点是用户节点
            if (targetFlowElement instanceof UserTask) {
                // 判断是否是会签
                UserTask userTask = (UserTask) targetFlowElement;
                if (userTask.getBehavior() instanceof ParallelMultiInstanceBehavior) {
                    ParallelMultiInstanceBehavior behavior = (ParallelMultiInstanceBehavior) userTask.getBehavior();
                    if (behavior != null && behavior.getCollectionExpression() != null) {
                        System.out.println("当前节点是会签");
                    }
                } else {
                    System.out.println("当前节点不是会签");
                }
                System.out.println("排他网关的下一节点是UserTask: id=" + targetFlowElement.getId() + ",name=" + targetFlowElement.getName());
                System.out.println("排他网关的下一节点CandidateUsers候选者" + ((UserTask) targetFlowElement).getCandidateUsers());

            } else if (targetFlowElement instanceof EndEvent) {
                System.out.println("排他网关的下一节点是EndEvent: 结束节点");
            } else if (targetFlowElement instanceof ServiceTask) {
                System.out.println("排他网关的下一节点是ServiceTask: 内部方法");
            } else if (targetFlowElement instanceof ExclusiveGateway) {
                //  setExclusiveGateway(targetFlowElement,data);
            } else if (targetFlowElement instanceof SubProcess) {
                System.out.println("排他网关的下一节点是SubProcess: 内部子流程");
            }
        }
    }
}
